package com.ll.domain.dingtalk.biz.impl;

import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.ll.app.api.req.*;
import com.ll.base.constant.LlConstants;
import com.ll.base.dto.ApiResultDTO;
import com.ll.base.util.DateUtil;
import com.ll.base.util.ListUtil;
import com.ll.base.util.RedisUtil;
import com.ll.base.util.ScalarUtil;
import com.ll.dal.po.SignupPO;
import com.ll.domain.classbase.base.SignupBaseService;
import com.ll.domain.classbase.biz.CourseDomainService;
import com.ll.domain.classbase.biz.SignupDomainService;
import com.ll.domain.classbase.dto.CourseDTO;
import com.ll.domain.classbase.enums.CourseStatusEnum;
import com.ll.domain.classbase.enums.SingupStatusEnum;
import com.ll.domain.dingtalk.biz.DingTalkRobotDomainService;
import com.ll.domain.ranking.biz.RankingDomainService;
import com.ll.domain.ranking.enums.RankingTypeEnum;
import com.ll.domain.user.dto.UserDTO;
import com.taobao.api.ApiException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class DingTalkRobotDomainServiceImpl implements DingTalkRobotDomainService {
    private final CourseDomainService courseDomainService;
    private final SignupBaseService signupBaseService;
    private final SignupDomainService signupDomainService;
    private final RankingDomainService rankingDomainService;
    private final RedisUtil redisUtil;

    @Override
    public String buildSignUp(UserDTO userDTO, String content) {
        List<CourseDTO> list = courseDomainService.list(PageCourseReqDTO.builder()
                .statues(Arrays.asList(CourseStatusEnum.开始中)).build());
        if (ScalarUtil.isEmpty(list)) {
            return "当前没有正在开始中的课程";
        }

        Map<Long, CourseDTO> courseMap = ListUtil.toMap(list, CourseDTO::getId);
        List<Long> cid = new ArrayList<>(courseMap.keySet());
        ListSignupReqDTO reqDTO = ListSignupReqDTO.builder()
                .dingUid(userDTO.getDingTalkUserId())
                .courseIds(cid)
                .status(Collections.singletonList(SingupStatusEnum.已报名))
                .build();
        List<SignupPO> signupPOS = signupBaseService.queryList(reqDTO);
        if (ScalarUtil.isEmpty(signupPOS)) {
            return "当前开始中的课程并您没有报名";
        }
        cid = ListUtil.toList(signupPOS, SignupPO::getCourseId);
        cid.forEach(r -> {
            SignupReqDTO signupReqDTO = SignupReqDTO.builder()
                    .teacherDingId("机器人签到")
                    .studentUserId(userDTO.getDingTalkUserId())
                    .courseId(r)
                    .build();
            signupDomainService.signup(signupReqDTO);
        });

        return "签到成功";
    }
    @Override
    public String buildApply(UserDTO userDTO, String content) {

        Integer courseIndex = ScalarUtil.getIntByString(content);
        Map<String, CourseDTO> courseMap = (Map<String, CourseDTO>) redisUtil.get(LlConstants.RedisContent.COURSE_LIST);
        if (courseIndex == null || courseMap == null || !courseMap.containsKey(String.valueOf(courseIndex))) {
            return "课号未找到，您可以通过 @机器人课程表 获取最新课号";

        }
        CourseDTO courseDTO = courseMap.get(String.valueOf(courseIndex));
        ApiResultDTO resultDTO = signupDomainService.apply(SignupApplyReqDTO.builder()
                .courseId(courseDTO.getId())
                .dingTalkUserId(userDTO.getDingTalkUserId())
                .build());
        if (!resultDTO.isSuccess()) {
            return resultDTO.getMessage();
        }

        courseDTO.setApplicants(courseDTO.getApplicants() + 1);
        courseMap.put(String.valueOf(courseIndex), courseDTO);
        redisUtil.set(LlConstants.RedisContent.COURSE_LIST, courseMap, LlConstants.RedisContent.COURSE_LIST_INVALID_TIME);
        return "您报名的["+courseDTO.getTitle()+"]成功，请在 "+DateUtil.parseDateToStr(courseDTO.getStartTime(), DateUtil.DATE_FORMAT_MMDDHHMI) +"之前到达现场签到";
    }
    @Override
    public String buildCancelApply(UserDTO userDTO, String content) {
        Integer courseIndex = ScalarUtil.getIntByString(content);
        Map<String, CourseDTO> courseMap = (Map<String, CourseDTO>) redisUtil.get(LlConstants.RedisContent.COURSE_LIST);
        if (courseIndex == null || courseMap == null || !courseMap.containsKey(String.valueOf(courseIndex))) {
            return "课号未找到，您可以通过 @机器人课程表 获取最新课号";
        }
        CourseDTO courseDTO = courseMap.get(String.valueOf(courseIndex));

        ApiResultDTO resultDTO = signupDomainService.cancelApply(SignupApplyReqDTO.builder()
                .courseId(courseDTO.getId())
                .dingTalkUserId(userDTO.getDingTalkUserId())
                .build());
        if (!resultDTO.isSuccess()) {
            return resultDTO.getMessage();
        }

        courseDTO.setApplicants(courseDTO.getApplicants() - 1);
        courseMap.put(String.valueOf(courseIndex), courseDTO);
        redisUtil.set(LlConstants.RedisContent.COURSE_LIST, courseMap, LlConstants.RedisContent.COURSE_LIST_INVALID_TIME);

        return "取消报名成功";
    }

    @Override
    public String buildDB(UserDTO userDTO, String content) {
        RankingTypeEnum type =RankingTypeEnum.美猎;
        if(content.contains("反曲")){
            type = RankingTypeEnum.反曲;
        }else if(content.contains("传统")){
            type = RankingTypeEnum.传统弓;
        }
        AddRankingReqDTO reqDTO = AddRankingReqDTO.builder()
                .studentUid(userDTO.getId())
                .type(type)
                .tenantId(LlConstants.DEFAULT_TENANT_ID)
                .build();
        rankingDomainService.add(reqDTO);
        return "申请打榜成功，请找教练监督打榜过程并且认证成绩";
    }


    @Override
    public boolean checkSign(String timestamp, String sign) {
        if (ScalarUtil.isEmpty(timestamp) || ScalarUtil.isEmpty(sign)) {
            return false;
        }
        String appSecret = "y_fhbMoJ5VGL7Ol46Ogt7jpAufoKx4zGJigGh_LGOypVCnurih_V33QxjhGwCNJ0";
        String stringToSign = timestamp + "\n" + appSecret;
        byte[] signData = null;
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(appSecret.getBytes("UTF-8"), "HmacSHA256"));
            signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        String sign2 = new String(Base64.encodeBase64(signData));
        log.info("sign : {} , sign2 {}", sign, sign2);
        return sign.equals(sign2);
    }


    @Override
    public String buildCourseList() {
        List<CourseDTO> list = courseDomainService.list(PageCourseReqDTO.builder().build());
        if (ScalarUtil.isEmpty(list)) {
            return "当前没有发布的课程";
        }
        StringBuilder result = new StringBuilder("当前课程列表： \n");
        Map<String, CourseDTO> map = new HashMap<>();
        for (int i = 1; i < list.size() + 1; i++) {
            CourseDTO courseDTO = list.get(i - 1);
            map.put(String.valueOf(i), courseDTO);
            result.append("-------").append("课号:").append(i).append("-------").append("\n")
                    .append("课程名称：").append(courseDTO.getTitle()).append("\n")
                    .append("课程类型：").append(courseDTO.getType().name()).append("\n")
                    .append("开始时间：").append(DateUtil.parseDateToStr(courseDTO.getStartTime(), DateUtil.DATE_FORMAT_MMDDHHMI)).append("\n")
                    .append("结束时间：").append(DateUtil.parseDateToStr(courseDTO.getEndTime(), DateUtil.DATE_FORMAT_MMDDHHMI)).append("\n")
                    .append("报名人数：（").append(courseDTO.getApplicants()).append("/").append(courseDTO.getMaxPeople()).append(")").append("\n");
        }
        result.append("---------------------");
        redisUtil.set(LlConstants.RedisContent.COURSE_LIST, map,DateUtil.getDistanceTimeHour());
        return result.toString();
    }


    @Override
    public void sendMsg(DingTalkClient client, String content) {
        try {
            OapiRobotSendRequest request = new OapiRobotSendRequest();
            request.setMsgtype("text");
            OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
            text.setContent(content);
            request.setText(text);
            OapiRobotSendResponse response = client.execute(request);
            System.out.println(response.getBody());
        } catch (ApiException e) {
            e.printStackTrace();
        }
    }
}
